package com.softtek.gui;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.io.IOException;

import javax.swing.BorderFactory;
import javax.swing.ImageIcon;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;

import javax.swing.event.HyperlinkEvent;
import javax.swing.event.HyperlinkListener;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;

import com.softtek.history.History;
import com.softtek.webbrowser.UnhandableContent;
import com.softtek.webbrowser.UrlManager;

import com.softtek.exception.JBException;
import com.softtek.webbrowser.JBProperties;


//TODO: display 404, 500 and binary file error as page;

public class Jbird extends JFrame implements ActionListener,
		HyperlinkListener, WindowListener, ListSelectionListener {

	private static final long serialVersionUID = 6078995293933507198L;

	private String mainTitle;

	private JPanel mainPanel;
	private JSplitPane workArea;
	private AddressBar addressBar;
	private HistoryPanel historyPanel;
	private StatusBar statusBar;

	private JEditorPane htmlDisplayer;

	private History historyHandler;
	private UrlManager urlHandler;
	
	private static Jbird jBirdMainWindow;
	
	/**
	 * Generic Constructor
	 */
	public Jbird() {
		
		mainTitle = JBProperties.getProperties().getProperty("MAIN_WINDOW_TITLE");
		
		final String tmpImageFolderPath = JBProperties.getProperties().getProperty("APP_DIR") +
										JBProperties.getProperties().getProperty("ASSET_DIR") +
										JBProperties.getProperties().getProperty("IMAGE_DIR");
		
		setTitle(mainTitle);
		setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		
		setIconImage(new ImageIcon(tmpImageFolderPath + JBProperties.getProperties().getProperty("APP_ICON")).getImage());
		
		mainPanel = new JPanel(new BorderLayout());
		historyHandler = new History();
		getContentPane().add(mainPanel);

		addWindowListener(this);

	}
	/**
	 * Initialize window components once the window is loaded and opened.
	 */
	public void windowOpened(WindowEvent e) {
		
		addressBar = new AddressBar(this);
		
		mainPanel.add(addressBar, BorderLayout.NORTH);

		htmlDisplayer = new JEditorPane();
		htmlDisplayer.setEditable(false);
		htmlDisplayer.addHyperlinkListener(this);

		htmlDisplayer.setBorder(BorderFactory.createLineBorder(null, 2));
		
		historyPanel = new HistoryPanel(this, historyHandler);
		
		statusBar = new StatusBar();
		
		workArea = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, historyPanel, new JScrollPane(htmlDisplayer));
		workArea.setDividerLocation(200);
		workArea.setOneTouchExpandable(true);
		
		mainPanel.add(workArea, BorderLayout.CENTER);
		
		mainPanel.add(statusBar, BorderLayout.SOUTH);
		
		setExtendedState(JFrame.MAXIMIZED_BOTH);
	}
	/**
	 * Sets window dislpay as visible
	 */
	public void display() {
		pack();
		setVisible(true);
	}
	/**
	 * Sets the text for the window title
	 * @param title
	 */
	public void setMainTitle(final String title) {
		mainTitle = new StringBuilder(JBProperties.getProperties().getProperty("MAIN_WINDOW_TITLE")
										+ " " + title).toString();
		setTitle(mainTitle);
	}

	/**
	 * Listen to actions and delegate them to specific method for handling.
	 */
	public void actionPerformed(final ActionEvent ae) {
		final Object source = ae.getSource();

		if (source == addressBar.getBackBtn()) {
			historyBack();
		} else if (source == addressBar.getForwardBtn()) {
			historyForward();
		} else if (source == addressBar.getAddressField()) {
			String url = ae.getActionCommand();
			
			if (!url.startsWith("http://")) {
				url = "http://" + url;
			}
			loadURL(url, true);
		}

	}

	/**
	 * Loads the URL to the JEditorPane
	 * 
	 * @param ae
	 * @return
	 */
	private void loadURL(final String urlAction, final Boolean refreshHistory) {

		String url = urlAction;

		if (urlHandler == null) {
			urlHandler = new UrlManager();
			urlHandler.setLoadContent(false); //allow jEditorPane to load content;
			
			urlHandler.addObserver(historyHandler);
			
			if(!urlHandler.getProxy().toString().equals("DIRECT")){
				//TODO: test on proxy environment
				
				System.getProperties().put("proxySet","true");
				System.getProperties().put("proxyHost",urlHandler.getProxy().toString());
				//System.getProperties().put("proxyPort",urlHandler.getProxy().);
			}

			
		}

		try {

			statusBar.setStatus("Loading: " + url);
			historyHandler.registerHistory(refreshHistory);
			
			final Boolean rendereableContent = urlHandler.getContent(url);
			htmlDisplayer.setContentType(urlHandler.getContentType());
			
			
			if(rendereableContent){
				htmlDisplayer.setPage(url);
				historyPanel.refresh(historyHandler);
			}else{
				htmlDisplayer.setContentType("text/html");
				htmlDisplayer.setText("<html><head></head><body></body>Binnary Content Loading</html>");
			}
			
			addressBar.getAddressField().setText(url);
			setTitle( mainTitle + url );
			statusBar.setStatus("DONE");

		} catch (IOException ioe) {
			displayErrorMessage("Unable to load URL: "+ ioe.getMessage() );
		} catch (UnhandableContent uex){
			displayErrorMessage("Warning: "+ uex.getMessage() );
		} catch (Exception ex){
			displayErrorMessage("Unknown error happened: \n" +
								"However it's a nice day, why dont you just \n " +
							    "forget what you are doing and go for a walk.\n" +
							    " =)");
		}

	}

	/**
	 * Goes to the previous history URL
	 * 
	 * @throws JBException
	 */
	private void historyBack(){
		String backUrl;

		if (historyHandler != null) {
			backUrl = historyHandler.back();
			if(backUrl != null && !backUrl.isEmpty()){
				loadURL(backUrl, false);
			}
			
		} 
	}
	/**
	 * Goes to the previous history URL
	 * 
	 * @throws JBException
	 */
	private void historyForward(){
		String forwardUrl;

		if (historyHandler != null) {
			forwardUrl = historyHandler.forward();
			if(forwardUrl != null && !forwardUrl.isEmpty()){
				loadURL(forwardUrl, false);
			}
			
		} 
	}
	
	/**
	 * Displays a error message for the user 
	 * @param message
	 */
	private void displayErrorMessage(final String message) {
		JOptionPane.showMessageDialog(this, message);
		System.out.println(message);
	}
	/**
	 * Handle the event caused by user clicks on links.
	 */
	public void hyperlinkUpdate(HyperlinkEvent he) {
		if (he.getEventType().equals(HyperlinkEvent.EventType.ACTIVATED)) {
			loadURL(he.getDescription(), true);
		} else if (he.getEventType().equals(HyperlinkEvent.EventType.ENTERED)) {
			statusBar.setStatus(he.getDescription());
		} else if (he.getEventType().equals(HyperlinkEvent.EventType.EXITED)) {
			statusBar.setStatus(StatusBar.NO_STATUS);
		}
	}
	/**
	 * Performs closing operations before window closes.
	 */
	public void windowClosing(WindowEvent we) {
		if (historyHandler != null) {
			historyHandler.persist();
		}
	}

	public void windowActivated(WindowEvent e) {}

	public void windowClosed(WindowEvent e) {}

	public void windowDeactivated(WindowEvent e) {}

	public void windowDeiconified(WindowEvent e) {}

	public void windowIconified(WindowEvent e) {}
	/**
	 * Handle History List events
	 */
	public void valueChanged(ListSelectionEvent e) {
		JList list = (JList) e.getSource();
		if(list.getSelectedValue() != null){
			loadURL( (String) list.getSelectedValue(), false);
		}
	}
	/**
	 * Execute the browser
	 * @param args
	 */
	public static void main(String[] args) {
		
		jBirdMainWindow = new Jbird();
		jBirdMainWindow.display();
		
	}
	

}
